package jhavelogger.reports;

import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Vector;

import javax.swing.*;
import jhavelogger.data.*;

import au.com.bytecode.opencsv.CSVWriter;
import com.toedter.calendar.*;

/**
 * Allows the user to generate reports of JHave logs.
 * @author Dexter Hoban
 */
public class ReportViewer extends JFrame {

    // Declare Components:
    private JCheckBox dateCheckBox, userCheckBox, cityCheckBox, regionCheckBox,
	    countryCheckBox;
    private JDateChooser startDate, endDate;
    private JComboBox cityComboBox, userComboBox, regionComboBox,
	    countryComboBox;
    private JLabel startDateLabel, endDateLabel;
    private JButton executeReportButton;
    private Vector<String> usernames, cities, regions, countries;
    private JMenuBar menuBar;
    private JMenu fileMenu, helpMenu;
    private JMenuItem exitAction, openPDFAction;

    public ReportViewer() {
	initComponents();
    }

    /**
     * Initializes GUI Interface
     */
    private void initComponents() {

	/*
	 * Initial frame Setup
	 */
	this.setLocation(200, 200);
	this.setResizable(false);
	this.setMinimumSize(new Dimension(350, 400));
	this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
	this.setTitle("Report Viewer");

	/*
	 * Setup the menu bar
	 */
	menuBar = new JMenuBar();
	fileMenu = new JMenu("File");
	helpMenu = new JMenu("Help");
	exitAction = new JMenuItem("Exit");
	exitAction.addActionListener(new ActionListener() {
	    public void actionPerformed(ActionEvent evt) {
		exitActionPerformed(evt);
	    }
	});
	openPDFAction = new JMenuItem("Open User Manual");
	openPDFAction.addActionListener(new ActionListener() {
	    public void actionPerformed(ActionEvent evt) {
		helpActionPerformed(evt);
	    }
	});
	menuBar.add(fileMenu);
	menuBar.add(helpMenu);
	fileMenu.add(exitAction);
	helpMenu.add(openPDFAction);
	this.setJMenuBar(menuBar);

	/*
	 * ComboBox Queries
	 */
	ConnectionFactory connectionFactory = new ConnectionFactory();
	try {
	    Connection connection = connectionFactory.createConnection();
	    JDBCLogDAO dao = new JDBCLogDAO(connection);
	    usernames = dao.getUsernames();
	    cities = dao.getCities();
	    regions = dao.getRegions();
	    countries = dao.getCountries();
	} catch (ClassNotFoundException e1) {
	    e1.printStackTrace();
	} catch (SQLException e1) {
	    e1.printStackTrace();
	} catch (IOException e1) {
	    e1.printStackTrace();
	}

	/*
	 * Initializes Panel and adds it to the frame.
	 */
	JPanel pane = new JPanel(new GridBagLayout());
	GridBagConstraints constraints = new GridBagConstraints();
	getContentPane().add(pane);

	/*
	 * Create dateCheckBox and adds it to the panel
	 */
	dateCheckBox = new JCheckBox("Select to specify dates.");
	constraints.gridx = 0;
	constraints.gridy = 0;
	constraints.ipadx = 2;
	constraints.ipady = 2;
	constraints.insets = new Insets(5, 5, 5, 5);
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	constraints.fill = GridBagConstraints.NONE;
	dateCheckBox.addItemListener(new java.awt.event.ItemListener() {
	    public void itemStateChanged(java.awt.event.ItemEvent evt) {
		dateCheckBoxActionPerformed(evt);
	    }
	});
	pane.add(dateCheckBox, constraints);

	/*
	 * Create startDateLabel and adds it to the panel
	 */
	startDateLabel = new JLabel("Start Date: ");
	constraints.gridx = 0;
	constraints.gridy = 1;
	constraints.gridheight = 1;
	constraints.gridwidth = 1;
	pane.add(startDateLabel, constraints);

	/*
	 * Create StartingDate date picker and adds it to the panel
	 */
	startDate = new JDateChooser();
	constraints.gridx = 1;
	constraints.gridy = 1;
	constraints.gridheight = 1;
	constraints.gridwidth = 1;
	startDate.setEnabled(false);
	startDate.setPreferredSize(new Dimension(175, 20));
	pane.add(startDate, constraints);

	/*
	 * Create endDateLabel and adds it to the panel
	 */
	endDateLabel = new JLabel("End Date: ");
	constraints.gridx = 0;
	constraints.gridy = 2;
	constraints.gridheight = 1;
	constraints.gridwidth = 1;
	pane.add(endDateLabel, constraints);

	/*
	 * Create EndingDate date picker and adds it to the panel
	 */
	endDate = new JDateChooser();
	constraints.gridx = 1;
	constraints.gridy = 2;
	constraints.gridheight = 1;
	constraints.gridwidth = 1;
	endDate.setPreferredSize(new Dimension(175, 20));
	endDate.setEnabled(false);
	pane.add(endDate, constraints);

	/*
	 * Creates userCheckBox and adds it to the panel
	 */
	userCheckBox = new JCheckBox("Select to specify user.");
	constraints.gridx = 0;
	constraints.gridy = 3;
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	constraints.fill = GridBagConstraints.NONE;
	userCheckBox.addItemListener(new java.awt.event.ItemListener() {
	    public void itemStateChanged(java.awt.event.ItemEvent evt) {
		userCheckBoxActionPerformed(evt);
	    }
	});
	pane.add(userCheckBox, constraints);

	/*
	 * Creates userComboBox and adds it to the panel
	 */
	userComboBox = new JComboBox(usernames);
	userComboBox.setSelectedIndex(-1);
	constraints.gridx = 0;
	constraints.gridy = 4;
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	userComboBox.setEnabled(false);
	userComboBox.setPreferredSize(new Dimension(250, 20));
	pane.add(userComboBox, constraints);

	/*
	 * Creates cityCheckBox and adds it to the panel
	 */
	cityCheckBox = new JCheckBox("Select to specify City.");
	constraints.gridx = 0;
	constraints.gridy = 5;
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	constraints.fill = GridBagConstraints.NONE;
	cityCheckBox.addItemListener(new java.awt.event.ItemListener() {
	    public void itemStateChanged(java.awt.event.ItemEvent evt) {
		cityCheckBoxActionPerformed(evt);
	    }
	});
	pane.add(cityCheckBox, constraints);

	/*
	 * Creates cityComboBox and adds it to the panel
	 */
	cityComboBox = new JComboBox(cities);
	cityComboBox.setSelectedIndex(-1);
	constraints.gridx = 0;
	constraints.gridy = 6;
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	cityComboBox.setEnabled(false);
	cityComboBox.setPreferredSize(new Dimension(250, 20));
	pane.add(cityComboBox, constraints);

	/*
	 * Creates regionCheckBox and adds it to the panel
	 */
	regionCheckBox = new JCheckBox("Select to specify region.");
	constraints.gridx = 0;
	constraints.gridy = 7;
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	constraints.fill = GridBagConstraints.NONE;
	regionCheckBox.addItemListener(new java.awt.event.ItemListener() {
	    public void itemStateChanged(java.awt.event.ItemEvent evt) {
		regionCheckBoxActionPerformed(evt);
	    }
	});
	pane.add(regionCheckBox, constraints);

	/*
	 * Creates regionComboBox and adds it to the panel
	 */
	regionComboBox = new JComboBox(regions);
	regionComboBox.setSelectedIndex(-1);
	constraints.gridx = 0;
	constraints.gridy = 8;
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	regionComboBox.setEnabled(false);
	regionComboBox.setPreferredSize(new Dimension(250, 20));
	pane.add(regionComboBox, constraints);

	/*
	 * Creates countryCheckBox and adds it to the panel
	 */
	countryCheckBox = new JCheckBox("Select to specify country.");
	constraints.gridx = 0;
	constraints.gridy = 9;
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	constraints.fill = GridBagConstraints.NONE;
	countryCheckBox.addItemListener(new java.awt.event.ItemListener() {
	    public void itemStateChanged(java.awt.event.ItemEvent evt) {
		countryCheckBoxActionPerformed(evt);
	    }
	});
	pane.add(countryCheckBox, constraints);

	/*
	 * Creates countryComboBox and adds it to the panel
	 */
	countryComboBox = new JComboBox(countries);
	countryComboBox.setSelectedIndex(-1);
	constraints.gridx = 0;
	constraints.gridy = 10;
	constraints.gridheight = 1;
	constraints.gridwidth = 2;
	countryComboBox.setEnabled(false);
	countryComboBox.setPreferredSize(new Dimension(250, 20));
	pane.add(countryComboBox, constraints);

	/*
	 * Generate Report Button
	 */
	executeReportButton = new JButton("Generate Report");
	constraints.gridx = 1;
	constraints.gridy = 11;
	constraints.gridheight = 2;
	constraints.gridwidth = 1;
	constraints.fill = GridBagConstraints.CENTER;
	executeReportButton.setPreferredSize(new Dimension(150, 50));
	executeReportButton
		.addActionListener(new java.awt.event.ActionListener() {
		    public void actionPerformed(ActionEvent evt) {
			executeReportActionPerformed(evt);
		    }
		});
	pane.add(executeReportButton, constraints);

	pack();
    }

    /**
     * Action for exit button - Exits on click
     */
    public void exitActionPerformed(ActionEvent evt) {
	System.exit(0);
    }

    /**
     * Action for help button - Opens User Manual
     */
    public void helpActionPerformed(ActionEvent evt) {
	File file = new File("docs/UserManual.pdf");
	try {
	    Desktop.getDesktop().open(file);
	} catch (IOException e) {
	}
    }

    /**
     * Action for dateCheckBox - Enables/Disables DateChoosers
     */
    private void dateCheckBoxActionPerformed(ItemEvent evt) {
	int state = evt.getStateChange();
	if (state == evt.SELECTED) {
	    startDate.setEnabled(true);
	    endDate.setEnabled(true);
	} else {
	    startDate.setEnabled(false);
	    endDate.setEnabled(false);
	    startDate.setDate(null);
	    endDate.setDate(null);
	}
    }

    /**
     * Action for userCheckBox - Enables/Disables Username parameter
     */
    private void userCheckBoxActionPerformed(ItemEvent evt) {
	int state = evt.getStateChange();
	if (state == evt.SELECTED) {
	    userComboBox.setEnabled(true);
	} else
	    userComboBox.setEnabled(false);
	userComboBox.setSelectedIndex(-1);
    }

    /**
     * Action for cityCheckBox - Enables/Disables city parameter
     */
    private void cityCheckBoxActionPerformed(ItemEvent evt) {
	int state = evt.getStateChange();
	if (state == evt.SELECTED) {
	    cityComboBox.setEnabled(true);
	} else
	    cityComboBox.setEnabled(false);
	cityComboBox.setSelectedIndex(-1);
    }

    /**
     * Action for regionCheckBox - Enables/Disables region parameter
     */
    private void regionCheckBoxActionPerformed(ItemEvent evt) {
	int state = evt.getStateChange();
	if (state == evt.SELECTED) {
	    regionComboBox.setEnabled(true);
	} else
	    regionComboBox.setEnabled(false);
	regionComboBox.setSelectedIndex(-1);
    }

    /**
     * Action for countryCheckBox - Enables/Disables region parameter
     */
    private void countryCheckBoxActionPerformed(ItemEvent evt) {
	int state = evt.getStateChange();
	if (state == evt.SELECTED) {
	    countryComboBox.setEnabled(true);
	} else
	    countryComboBox.setEnabled(false);
	countryComboBox.setSelectedIndex(-1);
    }

    /**
     * Action for generateReport Button - A query from the JDBCLogDAO class is called
     * to get the results of the query the user specified. A JFileChooser is opened and prompts
     * the user for the desired filename.  Prompts user when writing is complete.
     */
    protected void executeReportActionPerformed(ActionEvent evt) {
	try {
	    JFileChooser fileChooser = new JFileChooser();
	    int saveResult = fileChooser.showSaveDialog(this);
	    if (saveResult != JFileChooser.APPROVE_OPTION) {
		return;
	    }
	    File outFile = fileChooser.getSelectedFile();
	    
	    ConnectionFactory connectionFactoryExecute = new ConnectionFactory();
	    Connection connection = connectionFactoryExecute.createConnection();
	    JDBCLogDAO daoExecute = new JDBCLogDAO(connection);
	    List<String[]> results;
	    results = daoExecute.getQueryResults(
		    (String) userComboBox.getSelectedItem(),
		    startDate.getDate(), endDate.getDate(),
		    (String) cityComboBox.getSelectedItem(),
		    (String) regionComboBox.getSelectedItem(),
		    (String) countryComboBox.getSelectedItem());
	    
	    CSVWriter writer = new CSVWriter(new PrintWriter(
		    new FileOutputStream(outFile)));
	    writer.writeNext(new String[] { "LogID", "IP Address", "UserName",
		    "Algorithm", "Date", "City", "Region", "Country" });
	    writer.writeAll(results);
	    writer.close();
	    JOptionPane.showMessageDialog(this, "Done Writing to File.");
	} catch (ClassNotFoundException e1) {
	    e1.printStackTrace();
	} catch (SQLException e1) {
	    e1.printStackTrace();
	} catch (IOException e1) {
	    e1.printStackTrace();
	}
    }
}